home *** CD-ROM | disk | FTP | other *** search
/ Die Speccy' 97 / Die Speccy' 97.iso / amiga_system / the_aminet / comm / bbs / s342q07.lha / msgadd.c < prev    next >
C/C++ Source or Header  |  1994-11-15  |  25KB  |  1,100 lines

  1. /*
  2.  *                msgadd.c
  3.  *
  4.  * External Message handler.  For use with external OtherNet parsers.
  5.  */
  6.  
  7. /*
  8.  *                history
  9.  *
  10.  * 91Mar31 HAW  v1.4 -- support for virtual rooms.
  11.  * 90Aug13 HAW  v1.3 -- support for room archiving.
  12.  * 89Oct23 HAW  v1.2 -- support for incoming route mail.
  13.  * 88Nov05 HAW  Created.
  14.  */
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include "ctdl.h"
  18. #include "math.h"
  19. /*
  20.  *                contents
  21.  *
  22.  */
  23.  
  24. #define TITLE        "C86Net Message Adder(Amiga)"
  25. #define VERSION        "V3.42"
  26.  
  27. #define NO_ERROR    0
  28. #define BAD_ARGS    1
  29. #define BAD_TABLE       2
  30. #define NO_NODE        3
  31. #define FATAL        4
  32. #define LF_ERROR    5
  33.  
  34. int crtColumn;
  35. extern CONFIG      cfg;        /* Configuration variables      */
  36. extern MessageBuffer     msgBuf;    /* The -sole- message buffer    */
  37. extern aRoom       roomBuf;    /* Room buffer    */
  38. extern logBuffer   logBuf;
  39. extern FILE    *roomfl, *logfl;
  40. extern int    thisRoom;       /* Current room    */
  41. extern rTable      *roomTab;
  42. extern struct mBuf mFile1, mFile2;
  43. extern NetTable    *netTab;
  44. extern NetBuffer   netBuf;
  45. extern NetBuffer   netTemp;
  46. extern FILE    *netfl;
  47. extern LogTable    *logTab;
  48. extern int    thisNet;    /* Current node in use    */
  49. extern char    *APPEND_ANY;
  50. extern char    *APPEND_TEXT;
  51. extern FILE    *msgfl, *msgfl2;
  52. FILE    *GlobalFd;
  53. int    RouteSlot;
  54. extern FILE *upfd;
  55. char inNet = NORMAL_NET;
  56.  
  57. SListBase MailForward = { NULL, NULL, NULL, NULL, NULL };
  58. SListBase  Arch_base = { NULL, ChkNtoStr, NULL, FreeNtoStr, EatNMapStr };
  59. static char EOP = FALSE;
  60. char *R_SH_MARK =  "&&";
  61. char *NON_LOC_NET= "%%";
  62. char *LOC_NET =    "++";
  63.  
  64. #ifdef ANSI_PROTOTYPING
  65.  
  66. void GenInit(void);
  67. void Process(char *fn);
  68. int  GetOtherNetChar(void);
  69. int VirtualShared(int NetNo, label name);
  70. int VirtualExists(label name);
  71. void SaveIt(void);
  72. int  FindPerson(label nm, logBuffer *lbuf);
  73. int  FindRoom(label nm);
  74. int  FindNet(label nm, NetBuffer *netBuf);
  75. void AddVirtualField(char field, char *contents);
  76. void PutMessage(void);
  77. void HandleRouted(void);
  78. void AddField(char field, char *fValue);
  79. int  FindPos(void);
  80. void VirtualHandle(void);
  81. int MARecVirtualRoom(int VirtIndex);
  82.  
  83. #endif
  84.  
  85. int  mPrintf(char *format, ...) {return 0; }  /* stub to quiet the linker */
  86.  
  87.  
  88. /*
  89.  * crashout()
  90.  *
  91.  * Big error handler.
  92.  */
  93. void crashout(str)
  94. char *str;
  95. {
  96.     printf(str);
  97.     exit(FATAL);
  98. }
  99.  
  100. /*
  101.  * main()
  102.  *
  103.  * This is the main manager.
  104.  */
  105. int  main(int, char **);
  106. int  main(argc, argv)
  107. char **argv;
  108. int  argc;
  109. {
  110.     int rover;
  111.  
  112.     printf("%s %s\n%s\n\n", TITLE, VERSION, COPYRIGHT);
  113.  
  114.     /* not enough arguments?  Explain. */
  115.     if (argc < 3) {
  116.     printf("usage: MSGADD nodename file [ file ... ]\n");
  117.     printf("\nEach file may contain one or more messages in C86Net format.\n");
  118.     exit(BAD_ARGS);
  119.     }
  120.  
  121.     cfg.weAre = UTILITY;
  122.     if (!readSysTab(TRUE, TRUE)) {
  123.     exit(BAD_TABLE);
  124.     }
  125.  
  126.     if (access(LOCKFILE, 0) != -1) {
  127.     printf("Please do not run MsgAdd using Outside Commands.\n");
  128.     writeSysTab();
  129.     exit(LF_ERROR);
  130.     }
  131.  
  132.     GenInit();
  133.  
  134.     VirtInit();
  135.  
  136.     if (FindNet(argv[1], &netBuf) == ERROR) {
  137.     writeSysTab();
  138.     printf("Could not find node %s.\n", argv[1]);
  139.     exit(NO_NODE);
  140.     }
  141.  
  142.     for (rover = 2; rover < argc; rover++)
  143.     Process(argv[rover]);
  144.  
  145.     UpdVirtStuff();
  146.     writeSysTab();
  147.   return 0;
  148.   }
  149.  
  150. /*
  151.  * GenInit()
  152.  *
  153.  * This is a general initialization routine.
  154.  */
  155. void GenInit()
  156. {
  157.     SYS_FILE fn;
  158.  
  159.     initNetBuf(&netBuf);
  160.     initNetBuf(&netTemp);
  161.     makeSysName(fn, "ctdlnet.sys", &cfg.netArea);
  162.     openFile(fn, &netfl);
  163.  
  164.     initRoomBuf(&roomBuf);
  165.     makeSysName(fn, "ctdlroom.sys", &cfg.roomArea);
  166.     openFile(fn, &roomfl);
  167.  
  168.     InitMsgBase();
  169.  
  170.     initLogBuf(&logBuf);
  171.     makeSysName(fn, "ctdllog.sys", &cfg.logArea);
  172.     openFile(fn, &logfl);
  173.  
  174.     makeSysName(fn, "ctdlarch.sys", &cfg.roomArea);
  175.     MakeList(&Arch_base, fn, NULL);
  176. }
  177.  
  178. /*
  179.  * Process()
  180.  *
  181.  * This will process a file - read a file for all messages and stuff them
  182.  * into the message base.
  183.  */
  184. void Process(fn)
  185. char *fn;
  186. {
  187.     extern char *READ_ANY;
  188.  
  189.     if ((GlobalFd = fopen(fn, READ_ANY)) == NULL) {
  190.     printf("ERROR: Could not open %s.\n", fn);
  191.     return;
  192.     }
  193.  
  194.     while (getMessage(GetOtherNetChar, TRUE, TRUE, TRUE))
  195.     SaveIt();
  196.  
  197.     fclose(GlobalFd);
  198. }
  199.  
  200. /*
  201.  * GetOtherNetChar()
  202.  *
  203.  * This gets a character for getMessage.
  204.  */
  205. int GetOtherNetChar()
  206. {
  207.     int c;
  208.  
  209.     c = getc(GlobalFd);
  210.     if (c == EOF) return -1;
  211.     return c;
  212. }
  213.  
  214. /*
  215.  * SaveIt()
  216.  *
  217.  * This is charged with saving the message in the database.
  218.  *
  219.  * 1. If mail, must do recipient validation.
  220.  * 2. Must validate room.
  221.  */
  222. void SaveIt()
  223. {
  224.     int LogSlot, RoomSlot, place;
  225.     extern char *NON_LOC_NET, *LOC_NET;
  226.     char *fn;
  227.     char header[200];
  228.  
  229. #ifdef VIEWING
  230.     printf("mbauth=-%s-\n", msgBuf.mbauth);
  231.     printf("mbroom=-%s-\n", msgBuf.mbroom);
  232.     printf("mbdate=-%s-\n", msgBuf.mbdate);
  233.     printf("mbtime=-%s-\n", msgBuf.mbtime);
  234.     printf("mboname=-%s-\n", msgBuf.mboname);
  235.     printf("mborig=-%s-\n", msgBuf.mborig);
  236.     printf("mbto=-%s-\n", msgBuf.mbto);
  237.     printf("mbsrcId=-%s-\n", msgBuf.mbsrcId);
  238.     printf("mbtext=-%s-\n", msgBuf.mbtext);
  239.     printf("\n");
  240. #endif
  241.  
  242.     if (VirtualExists(msgBuf.mbroom) != ERROR) {
  243.     VirtualHandle();
  244.     return ;
  245.     }
  246.  
  247.     if (strLen(msgBuf.mbaddr) != 0) {
  248.     HandleRouted();
  249.     }
  250.     else if (strCmpU(msgBuf.mbroom, "mail") == SAMESTRING) {
  251.     if ((LogSlot = FindPerson(msgBuf.mbto, &logBuf)) == ERROR) {
  252.         printf("Could not deliver Mail to '%s', does not exist.\n",
  253.                             msgBuf.mbto);
  254.         return ;
  255.     }
  256.     noteAMessage(logBuf.lbMail, MAILSLOTS, cfg.newest+1, cfg.catSector);
  257.     putLog(&logBuf, LogSlot);
  258.     }
  259.     else {
  260.     if ((RoomSlot = FindRoom(msgBuf.mbroom)) == ERROR) {
  261.         printf("Message meant for non-existent room '%s' not incorporated.\n",
  262.                         msgBuf.mbroom);
  263.         return ;
  264.     }
  265.     noteAMessage(roomBuf.msg, MSGSPERRM, cfg.newest+1, cfg.catSector);
  266.     roomTab[RoomSlot].rtlastMessage = cfg.newest + 1;
  267.     putRoom(RoomSlot);
  268.     if ((place = FindPos()) == ERROR)
  269.         printf("WARNING: msg for %s is not formally shared.\n",
  270.                             msgBuf.mbroom);
  271.  
  272.     if (roomBuf.rbShareType != PEON &&
  273.                 netBuf.netRooms[place].mode != PEON)
  274.         strCpy(msgBuf.mbaddr, NON_LOC_NET);
  275.     else
  276.         strCpy(msgBuf.mbaddr, LOC_NET);
  277.  
  278.     if (roomBuf.rbflags.ARCHIVE == 1) {
  279.         fn = SearchList(&Arch_base, NtoStrInit(thisRoom, "", 0, TRUE));
  280.         if ((upfd = fopen(fn, APPEND_TEXT)) != NULL) {
  281.         header[0] = 0;
  282.             if (msgBuf.mbdate[ 0])
  283.             sPrintf(lbyte(header), "   %s ", msgBuf.mbdate);
  284.             if (msgBuf.mbtime[ 0] && sendTime)
  285.             sPrintf(lbyte(header), "%s ", msgBuf.mbtime);
  286.             if (msgBuf.mbauth[ 0]) {
  287.             sPrintf(lbyte(header), "from %s",    msgBuf.mbauth );
  288.             }
  289.             NormStr(msgBuf.mboname);
  290.             if (msgBuf.mboname[0]) {
  291.             sPrintf(lbyte(header), " @ %s", msgBuf.mboname);
  292.             if (msgBuf.mbdomain[0])
  293.                 sPrintf(lbyte(header), cfg.DomainDisplay,
  294.                             msgBuf.mbdomain);
  295.             }
  296.  
  297.             if (msgBuf.mbto[   0]) {
  298.             sPrintf(lbyte(header), " to %s", msgBuf.mbto);
  299.             }
  300.         fprintf(upfd, "%s\n", header);
  301.         crtColumn = 1;
  302.         mFormat(msgBuf.mbtext);
  303.         fprintf(upfd, "\n");
  304.         fclose(upfd);
  305.         }
  306.         }
  307.     }
  308.     strCpy(msgBuf.mborig, netBuf.netId);
  309.     PutMessage();
  310.     cfg.newest++;
  311.  
  312.     cfg.catSector   = mFile1.thisSector;
  313.     cfg.catChar     = mFile1.thisChar;
  314. }
  315.  
  316. SListBase FwdAliasii;    /* keeps some other stuff happy */
  317. char onConsole = FALSE, remoteSysop = FALSE;
  318. int  callSlot = ERROR;
  319. /*
  320.  * HandleRouted()
  321.  *
  322.  * This should handle mail routing incoming.
  323.  */
  324. void HandleRouted()
  325. {
  326.     char     *AltName;
  327.     label    Name, Id, temp;
  328.     SYS_FILE fn;
  329.     extern void (*NetPrintTarget)(char *fmt, ...);
  330.     extern int  (*ToFileWork)();
  331.  
  332.     /* no find? */
  333.     if ((RouteSlot = FindNet(msgBuf.mbaddr, &netTemp)) == ERROR) {
  334.     return;
  335.     }
  336.  
  337.     /* yes, found, data in netTemp - will we do the routing? */
  338.     if (!cfg.BoolFlags.RouteMail || !netTemp.nbflags.RouteTo) {
  339.     return;
  340.     }
  341.  
  342.     /* yes, we'll do the routing.  Now to figure it out. */
  343.     strCpy(Name, netTemp.netName);
  344.     strCpy(Id, netTemp.netId);
  345.  
  346.     if ((AltName = UseNetAlias(Name, TRUE)) != NULL)
  347.     strCpy(Name, AltName);
  348.  
  349.     if (FindRouteSlot() == ERROR) {
  350.     return;
  351.     }
  352.  
  353.     /* Ugly ugly kludge until we figure out how nbHiRouteInd is wrong */
  354.     if (netTemp.nbHiRouteInd < 0) netTemp.nbHiRouteInd = 0;
  355.     sPrintf(temp, "R%d.%d", RouteSlot, netTemp.nbHiRouteInd++);
  356.  
  357.     makeSysName(fn, temp, &cfg.netArea);
  358.  
  359.     if ((upfd = safeopen(fn, APPEND_ANY)) == NULL) {
  360.     return;
  361.     }
  362.  
  363.     fprintf(upfd, "%-20s", Id);
  364.     putc(0, upfd);
  365.     fprintf(upfd, "%-20s", Name);
  366.     putc(0, upfd);
  367.  
  368.     NetPrintTarget = ToFile;
  369.     StartEncode(putFLChar);
  370.     ToFileWork = Encode;
  371.     prNetStyle(TRUE, Encode, FALSE, "");
  372.     StopEncode();
  373.     fclose(upfd);
  374.     netTemp.nbflags.HasRouted = TRUE;
  375.  
  376.     putNet(RouteSlot, &netTemp);
  377. }
  378.  
  379. /*
  380.  * FindPerson()
  381.  *
  382.  * This loads the log record for the named person.
  383.  * RETURNS: ERROR if not found, else log record #
  384.  * (stolen from LOG.C)
  385.  */
  386. int FindPerson(name, lBuf)
  387. char      *name;
  388. logBuffer *lBuf;
  389. {
  390.     int  h, i, foundIt, logNo;
  391.  
  392.     if (strCmpU(name, "Citadel") != SAMESTRING) {
  393.     h   = hash(name);
  394.     for (foundIt = i = 0;  i < cfg.MAXLOGTAB && !foundIt;  i++) {
  395.         if (logTab[i].ltnmhash == h) {
  396.         getLog(lBuf, logNo = logTab[i].ltlogSlot);
  397.         if (lBuf->lbflags.L_INUSE &&
  398.                 strCmpU(name, lBuf->lbname) == SAMESTRING) {
  399.             foundIt = TRUE;
  400.         }
  401.         }
  402.     }
  403.     }
  404.     else foundIt = FALSE;
  405.     if (!foundIt)    return ERROR;
  406.     else    return logNo;
  407. }
  408.  
  409. /*
  410.  * findRoom()
  411.  *
  412.  * This function should find the named room.  Return ERROR if not found.
  413.  */
  414. int FindRoom(nm)
  415. label nm;
  416. {
  417.     int rover;
  418.  
  419.     for (rover = 0; rover < MAXROOMS; rover++)
  420.     if (strCmpU(roomTab[rover].rtname, nm) == SAMESTRING) {
  421.         getRoom(rover);
  422.         return rover;
  423.     }
  424.  
  425.     return ERROR;
  426. }
  427.  
  428. /*
  429.  * noteAMessage()
  430.  *
  431.  * This function notes a message in a message array.  Stolen from MSG.C.
  432.  */
  433. void noteAMessage(base, slots, id, loc)
  434. MSG_NUMBER  id;
  435. SECTOR_ID   loc;
  436. theMessages *base;
  437. int    slots;
  438. {
  439.     int  i;
  440.  
  441.     /* store into current room: */
  442.     /* slide message pointers down to make room for this one:       */
  443.     for (i = 0;  i < slots - 1;  i++) {
  444.     base[i].rbmsgLoc  = base[i+1].rbmsgLoc;
  445.     base[i].rbmsgNo   = base[i+1].rbmsgNo ;
  446.     }
  447.  
  448.     /* slot this message in:    */
  449.     base[slots-1].rbmsgNo     = id ;
  450.     base[slots-1].rbmsgLoc    = loc;
  451. }
  452.  
  453. /*
  454.  * FindNet()
  455.  *
  456.  * This function will find the named node.  Stolen from searchNameNet/NETMISC.
  457.  */
  458. int  FindNet(label nm, NetBuffer *nBuf)
  459. {
  460.     int rover;
  461.  
  462.     for (rover = 0; rover < cfg.netSize; rover++) {
  463.     if (netTab[rover].ntflags.in_use &&
  464.         hash(nm) == netTab[rover].ntnmhash) {
  465.         getNet(rover, nBuf);
  466.         if (strCmpU(nBuf->netName, nm) == SAMESTRING)
  467.         return rover;
  468.     }
  469.     }
  470.     return ERROR;
  471. }
  472.  
  473. /*
  474.  * FindPos()
  475.  *
  476.  * This finds the spot in the shared room array for the node that matches up
  477.  * with the current room.
  478.  */
  479. int FindPos()
  480. {
  481.     int rover;
  482.  
  483.     for (rover = 0; rover < SHARED_ROOMS; rover++)
  484.     if (isSharedRoom(thisNet, rover) &&
  485.             netRoomSlot(rover) == thisRoom &&
  486.                 netGen(thisNet, rover)  == roomBuf.rbgen)
  487.         return rover;
  488.  
  489.     return ERROR;
  490. }
  491.  
  492. /*
  493.  * VirtualHandle()
  494.  *
  495.  * This function will handle a message destined for a virt room.
  496.  */
  497. void VirtualHandle()
  498. {
  499.     int Vindex;
  500.  
  501.     if ((Vindex = VirtualShared(thisNet, msgBuf.mbroom)) == ERROR) {
  502.     printf("Virtual room %s not shared with %s, message not saved.\n",
  503.                 msgBuf.mbroom, netBuf.netName);
  504.     return;
  505.     }
  506.     MARecVirtualRoom(Vindex);
  507. }
  508.  
  509. /*********** These functions stolen & modified from VIRT2.C ***************/
  510.  
  511. extern VirtualRoom *VRoomTab;
  512. extern VirtNet     *VirtNetList;
  513. extern int  VirtSize, VNetSize;
  514. /*
  515.  * MARecVirtualRoom()
  516.  *
  517.  * This function receives a virtual room from another system.
  518.  */
  519. int MARecVirtualRoom(int VirtIndex)
  520. {
  521.     int        VirtNo;
  522.     MSG_NUMBER  rover;
  523.     char    *distance, fn[50];
  524.     extern FILE *upfd;
  525.     extern char *WRITE_ANY;
  526.  
  527.     VirtNo = VirtNetList[thisNet].VirtList[VirtIndex].WhichVirt;
  528.  
  529.     if (VirtNetList[thisNet].VirtList[VirtIndex].mode != PEON) {
  530.     distance = LD_DIR;
  531.     rover = VRoomTab[VirtNo].vrHiLD + 1l;
  532.     VRoomTab[VirtNo].vrChanged |= LD_CHANGE;
  533.     }
  534.     else {
  535.     distance = LOCAL_DIR;
  536.     rover = VRoomTab[VirtNo].vrHiLocal + 1l;
  537.     VRoomTab[VirtNo].vrChanged |= LOC_CHANGE;
  538.     }
  539.     CreateVAName(fn, VirtNo, distance, rover);
  540.  
  541.     if ((upfd = fopen(fn, WRITE_ANY)) != NULL) {
  542.     if (msgBuf.mbauth[0])
  543.         AddVirtualField('A', msgBuf.mbauth);
  544.     if (msgBuf.mbdate[0])
  545.         AddVirtualField('D', msgBuf.mbdate);
  546.     if (msgBuf.mbtime[0])
  547.         AddVirtualField('C', msgBuf.mbtime);
  548.     if (msgBuf.mboname[0])
  549.         AddVirtualField('N', msgBuf.mboname);
  550.     if (msgBuf.mborig[0])
  551.         AddVirtualField('O', msgBuf.mborig);
  552.     if (msgBuf.mbroom[0])
  553.         AddVirtualField('R', msgBuf.mbroom);
  554.     if (msgBuf.mbsrcId[0])
  555.         AddVirtualField('S', msgBuf.mbsrcId);
  556.     if (msgBuf.mbto[0])
  557.         AddVirtualField('T', msgBuf.mbto);
  558.     if (msgBuf.mbOther[0])
  559.         AddVirtualField('P', msgBuf.mbOther);
  560.     if (msgBuf.mbdomain[0])
  561.         AddVirtualField('X', msgBuf.mbdomain);
  562.     if (msgBuf.mbtext[0])
  563.         AddVirtualField('M', msgBuf.mbtext);
  564.     fclose(upfd);
  565.     }
  566.     else
  567.     printf("Unable to open %s!\n", fn);
  568.  
  569.     VirtSummary();
  570.     return 0;
  571. }
  572.  
  573. /*
  574.  * AddVirtualField()
  575.  *
  576.  * This function adds a field to a virtual room message.
  577.  */
  578. void AddVirtualField(char field, char *contents)
  579. {
  580.     fprintf(upfd, "%c%s", field, contents);
  581.     fputc(0, upfd);
  582. }
  583.  
  584. /*
  585.  * VirtualExists()
  586.  *
  587.  * This function returns an index to given room, if exists.
  588.  */
  589. int VirtualExists(label name)
  590. {
  591.     int rover;
  592.  
  593.     for (rover = 0; rover < VirtSize; rover++)
  594.     if (strCmpU(VRoomTab[rover].vrName, name) == SAMESTRING) return rover;
  595.  
  596.     return ERROR;
  597. }
  598.  
  599. /*
  600.  * VirtualShared()
  601.  *
  602.  * This function returns an index into current net's virtual index.
  603.  */
  604. int VirtualShared(int NetNo, label name)
  605. {
  606.     int rover, VirtNo;
  607.  
  608.     if ((VirtNo = VirtualExists(name)) == ERROR) return ERROR;
  609.  
  610.     for (rover = 0; rover < VIRT_LIMIT; rover++)
  611.     if (VirtNetList[NetNo].VirtList[rover].WhichVirt == VirtNo)
  612.         return rover;
  613.     return ERROR;
  614. }
  615.  
  616. /*********** These functions stolen & modified from MSG.C ***************/
  617.  
  618. /*
  619.  * doActualWrite()
  620.  *
  621.  * This should allow automatic bkp of msg file from RAM.
  622.  */
  623. char doActualWrite(whichmsg, mFile, c)
  624. FILE    *whichmsg;
  625. struct mBuf *mFile;
  626. char    c;
  627. {
  628.     MSG_NUMBER temp;
  629.     int    toReturn = 0;
  630.  
  631.     if (mFile->sectBuf[mFile->thisChar] == 0xFF)  {
  632.     /* obliterating a msg   */
  633.     toReturn = 1;
  634.     }
  635.  
  636.     mFile->sectBuf[mFile->thisChar]   = c;
  637.  
  638.     mFile->thisChar    = ++mFile->thisChar % MSG_SECT_SIZE;
  639.  
  640.     if (mFile->thisChar == 0) { /* time to write sector out and get next: */
  641.     temp = mFile->thisSector;
  642.     temp *= MSG_SECT_SIZE;
  643.     fseek(whichmsg, temp, 0);
  644.     crypte(mFile->sectBuf, MSG_SECT_SIZE, 0);
  645.     if (fwrite(mFile->sectBuf, MSG_SECT_SIZE, 1, whichmsg) != 1) {
  646.         crashout("?putMsgChar-write fail");
  647.     }
  648.  
  649.     mFile->thisSector = ++mFile->thisSector % cfg.maxMSector;
  650.     temp = mFile->thisSector;
  651.     temp *= MSG_SECT_SIZE;
  652.     fseek(whichmsg, temp, 0);
  653.     if (fread(mFile->sectBuf, MSG_SECT_SIZE, 1, whichmsg) != 1) {
  654.         crashout("?putMsgChar-read fail");
  655.     }
  656.     crypte(mFile->sectBuf, MSG_SECT_SIZE, 0);
  657.     }
  658.     return (char) toReturn;
  659. }
  660.  
  661. /*
  662.  * doFlush()
  663.  *
  664.  * This will do actual writeup for specified msg file.
  665.  */
  666. void doFlush(whichmsg, mFile)
  667. FILE *whichmsg;
  668. struct mBuf *mFile;
  669. {
  670.     long int s;
  671.  
  672.     s = mFile->thisSector;
  673.     s *= MSG_SECT_SIZE;
  674.     fseek(whichmsg, s, 0);
  675.     crypte(mFile->sectBuf, MSG_SECT_SIZE, 0);
  676.     if (fwrite(mFile->sectBuf, MSG_SECT_SIZE, 1, whichmsg) != 1) {
  677.     crashout("?ctdlmsg.sys write fail");
  678.     }
  679.     crypte(mFile->sectBuf, MSG_SECT_SIZE, 0);
  680.     fflush(whichmsg);
  681. }
  682.  
  683. /*
  684.  * flushMsgBuf()
  685.  *
  686.  * This wraps up writing a message to disk, takes into account 2nd msg file if
  687.  * necessary.
  688.  */
  689. void flushMsgBuf()
  690. {
  691.     doFlush(msgfl, &mFile1);
  692.     if (cfg.BoolFlags.mirror)
  693.     doFlush(msgfl2, &mFile2);
  694. }
  695.  
  696. /*
  697.  * putMessage()
  698.  *
  699.  * This function stores a message to disk.
  700.  * Always called before noteMessage() -- newest not ++ed yet.
  701.  * Returns: TRUE on successful save, else FALSE
  702.  */
  703. void PutMessage()
  704. {
  705.     label temp;
  706.     extern char *ALL_LOCALS, *WRITE_LOCALS;
  707.     extern char *R_SH_MARK, *LOC_NET, *NON_LOC_NET;
  708.     char  *s;
  709.  
  710.     startAt(msgfl, &mFile1, cfg.catSector, cfg.catChar);
  711.         /* tell putMsgChar where to write   */
  712.     if (cfg.BoolFlags.mirror)
  713.     startAt(msgfl2, &mFile2, cfg.catSector, cfg.catChar);
  714.  
  715.     putMsgChar(0xFF);    /* start-of-message    */
  716.  
  717.     /* write message ID */
  718.     sPrintf(temp, "%lu", cfg.newest + 1);
  719.     AddField(0, temp);
  720.  
  721.     /* write date:      */
  722.     if (msgBuf.mbdate[0]) {
  723.     AddField('D', msgBuf.mbdate);
  724.     }
  725.     else {
  726.     AddField('D', "????");
  727.     }
  728.  
  729.     /* write time:      */
  730.     if (msgBuf.mbtime[0]) {
  731.     AddField('C', msgBuf.mbtime);
  732.     }
  733.     else {
  734.     AddField('C', "!!!!");
  735.     }
  736.  
  737.     /* write author's name out:    */
  738.     if (msgBuf.mbauth[0]) {
  739.     AddField('A', msgBuf.mbauth);
  740.     }
  741.  
  742.     /* write room name out:    */
  743.     AddField('R', msgBuf.mbroom);
  744.  
  745.     if (msgBuf.mbto[0]) {       /* private message -- write addressee   */
  746.     AddField('T', msgBuf.mbto);
  747.     }
  748.  
  749.     if (msgBuf.mbaddr[0]) {     /* net message routing    */
  750.     if (strCmpU(msgBuf.mbaddr, R_SH_MARK  ) == SAMESTRING ||
  751.         strCmpU(msgBuf.mbaddr, NON_LOC_NET) == SAMESTRING) {
  752.         AddField('N', msgBuf.mboname);
  753.         if (msgBuf.mborig[0])   {
  754.         AddField('O', msgBuf.mborig);
  755.         }
  756.         roomTab[thisRoom].rtlastNet = cfg.newest + 1;
  757.     }
  758.     else if (strCmpU(msgBuf.mbaddr, LOC_NET    ) == SAMESTRING) {
  759.         AddField('N', msgBuf.mboname);
  760.         if (msgBuf.mborig[0])   {
  761.         AddField('O', msgBuf.mborig);
  762.         }
  763.     }
  764.  
  765.     sPrintf(temp, "%s%d", msgBuf.mbaddr, thisNet);
  766.     AddField('Q', temp);
  767.     }
  768.     else {
  769.     if (msgBuf.mboname[0]) {
  770.         AddField('N', msgBuf.mboname);
  771.     }
  772.     if (msgBuf.mborig[0])   {
  773.         AddField('O', msgBuf.mborig);
  774.     }
  775.     }
  776.  
  777.     if (msgBuf.mbdomain[0])   {
  778.     AddField('X', msgBuf.mbdomain);
  779.     }
  780.  
  781.     if (msgBuf.mbsrcId[0])   {
  782.     AddField('S', msgBuf.mbsrcId);
  783.     }
  784.  
  785.     if (msgBuf.mbOther[0])   {
  786.     AddField('P', msgBuf.mbOther);
  787.     }
  788.  
  789.     /* write message text by hand because it would overrun AddField buffer: */
  790.     putMsgChar('M');    /* M-for-message.       */
  791.     for (s = msgBuf.mbtext;  *s;  s++) putMsgChar(*s);
  792.  
  793.     putMsgChar(0);      /* null to end text    */
  794.     flushMsgBuf();
  795.  
  796. }
  797.  
  798. /*
  799.  * AddField()
  800.  *
  801.  * This adds a field to the message base.
  802.  */
  803. void AddField(field, fValue)
  804. char field;
  805. char *fValue;
  806. {
  807.     if (field) putMsgChar(field);
  808.     while (*fValue) putMsgChar(*fValue++);
  809.     putMsgChar(0);    /* End field. */
  810. }
  811.  
  812. /*
  813.  * putMsgChar()
  814.  *
  815.  * This function writes successive message chars to disk.
  816.  * Globals:    thisChar=       thisSector=
  817.  * Returns:    ERROR if problems else TRUE.
  818.  */
  819. int putMsgChar(c)
  820. char c;
  821. {
  822.     int  toReturn;
  823.     int  count1, count2;
  824.  
  825.     toReturn = TRUE;
  826.     count1 = doActualWrite(msgfl, &mFile1, c);
  827.     if (cfg.BoolFlags.mirror) {
  828.     count2 = doActualWrite(msgfl2, &mFile2, c);
  829.     if (count1 != count2) printf("Mirror msg count discrepancy!");
  830.     }
  831.     if (count1)
  832.     ++cfg.oldest;
  833.     return toReturn;
  834. }
  835.  
  836. static label SearchResult;
  837. static char  *SearchTarget, GetAlias;
  838. /*
  839.  * UseNetAlias()
  840.  *
  841.  * This function will find a usenet alias or the converse.
  842.  */
  843. char *UseNetAlias(char *Name, char FindAlias)
  844. {
  845.     void *EatTrans();
  846.     SListBase Dummy = { NULL, NULL, NULL, NULL, EatTrans };
  847.     SYS_FILE fn;
  848.     char *c;
  849.  
  850.     SearchResult[0] = 0;
  851.     SearchTarget = Name;
  852.     if (!FindAlias) while ((c = strchr(Name, ' ')) != NULL) *c = '_';
  853.     makeSysName(fn, "st-alias.sys", &cfg.roomArea);
  854.     GetAlias = FindAlias;
  855.     MakeList(&Dummy, fn, NULL);    /* CHEAT!  WHEEEEEE! */
  856.     if (strLen(SearchResult) == 0) return NULL;
  857.     return SearchResult;
  858. }
  859.  
  860. /*
  861.  * EatTrans()
  862.  *
  863.  * This function will eat a line of for the alias mapping.
  864.  */
  865. void *EatTrans(char *line)
  866. {
  867.     char *c;
  868.  
  869.     if ((c = strchr(line, ' ')) != NULL) {
  870.     *c = 0;
  871.     if (GetAlias) {        /* check second field */
  872.         if (strCmpU(c + 1, SearchTarget) == SAMESTRING) {
  873.         strCpy(SearchResult, line);
  874.         }
  875.     }
  876.     else {            /* check first field */
  877.         if (strCmpU(line, SearchTarget) == SAMESTRING) {
  878.         strCpy(SearchResult, c + 1);
  879.         }
  880.     }
  881.     }
  882.     return NULL;
  883. }
  884.  
  885. /*
  886.  * FindRouteSlot()
  887.  *
  888.  * This function will find the slot of routing node.  If found, netTemp will
  889.  * contain the new slot, as will RouteSlot.
  890.  */
  891. int FindRouteSlot()
  892. {
  893.     /*
  894.      * first check to see if we're the direct (final) link, either
  895.      * expressly or because the route is outdated.
  896.      */
  897.     if (!DirectRoute(&netTemp))    /* expressly?   */
  898.     getNet((RouteSlot = netTemp.nbRoute), &netTemp);
  899.  
  900.     return RouteSlot;
  901. }
  902.  
  903. /*
  904.  * DirectRoute()
  905.  *
  906.  * This will discover if we directly or indirectly talk to this node.
  907.  */
  908. char DirectRoute(NetBuffer *n)
  909. {
  910.     return (char) (n->nbRoute == -1 ||    /* expressly?   */
  911.     !netTab[n->nbRoute].ntflags.in_use ||    /* outdated?    */
  912.     netTab[n->nbRoute].ntGen != n->nbRouteGen);/* outdated?*/
  913. }
  914.  
  915. /*
  916.  * getNetChar()
  917.  *
  918.  * This gets a character from a network temporary file.
  919.  */
  920. int getNetChar()
  921. {
  922.     return -1;        /* actually, this should never be called.    */
  923. }
  924.  
  925. /*
  926.  * SepNameSystem()
  927.  *
  928.  * This will parse an Other Recipient spec.
  929.  */
  930. char SepNameSystem(char *string, char *person, char *system, NetBuffer *buf)
  931. {
  932.     char *c;
  933.     int  n;
  934.     char work[NAMESIZE * 3];    /* should be sufficient */
  935.  
  936.     strCpy(work, string);
  937.     if ((c = strchr(work, '@')) == NULL)
  938.     return NOT_SYSTEM;
  939.  
  940.     /* find leading spaces of "name @ system" format */
  941.     for (n = 1; c[n] == ' ' && c[n]; n++)
  942.     ;
  943.  
  944.     if (strLen(c + n) >= NAMESIZE)
  945.     return BAD_FORMAT;
  946.  
  947.     strCpy(system, c + n);
  948.     if (searchNameNet(c + n, buf) == ERROR)  /* bad - set signal of it */
  949.     return NO_SYSTEM;
  950.  
  951.     *c = 0;
  952.     CleanEnd(work);    /* kill trailing spaces */
  953.     if (strLen(work) >= NAMESIZE)
  954.     return BAD_FORMAT;
  955.  
  956.     strCpy(person, work);
  957.  
  958.     return IS_SYSTEM;
  959. }
  960.  
  961. #define WeServe(x)    SearchList(&Serves, x)
  962. extern SListBase Serves;
  963. /*
  964.  * LocalName()
  965.  *
  966.  * This takes a string of form <system> _ <domain> and attempts to discover if
  967.  * this domain mapped system is actually a local.  This is used when we're
  968.  * sending mail and are trying to find out if a Who Else override needs to be
  969.  * generated.  Ugly kludge, but, hey, that's what programming's all about, eh?
  970.  */
  971. char *LocalName(char *system)
  972. {
  973.     char *domain, *System;
  974.  
  975.     if ((domain = strchr(system, '_')) == NULL) return system;
  976.     domain += 2;    /* always preceded by a space -- or so we assume */
  977.  
  978.     if (strCmpU(domain, cfg.codeBuf + cfg.nodeDomain) == SAMESTRING ||
  979.          WeServe(domain) != NULL) {
  980.     System = strdup(system);
  981.     if ((domain = strchr(System, ' ')) == NULL)
  982.         return system;    /* should never happen, though */
  983.     *domain = NULL;
  984.     if (searchNameNet(System, &netTemp) != ERROR) {
  985.         free(System);
  986.         return netTemp.netName;
  987.     }
  988.     free(System);
  989.     }
  990.     return system;
  991. }
  992.  
  993. /*
  994.  * mFormat()
  995.  *
  996.  * This function formats a string to modem and console.
  997.  */
  998. void mFormat(char *string)
  999. {
  1000.     char wordBuf[MAXWORD];
  1001.     int  i;
  1002.  
  1003.     for (i = 0;  string[i]; ) {
  1004.     i = getWord(wordBuf, string, i, MAXWORD);
  1005.     putWord(wordBuf);
  1006.     }
  1007. }
  1008.  
  1009. /*
  1010.  * getWord()
  1011.  *
  1012.  * This function fetches one word from current message.
  1013.  */
  1014. int getWord(char *dest, char *source, int offset, int lim)
  1015. {
  1016.     int i, j;
  1017.  
  1018.     /* skip leading blanks if any */
  1019.     for (i = 0;  source[offset+i] ==' ' && i < lim - 1;  i++);
  1020.  
  1021.     /* step over word */
  1022.     for (;
  1023.  
  1024.     source[offset+i]   != ' '     &&
  1025.     i    <  lim - 1 &&
  1026.     source[offset+i]   != 0;
  1027.  
  1028.     i++
  1029.     );
  1030.  
  1031.     if (source[offset + i - 1] != '\n')
  1032.     /* pick up any trailing blanks */
  1033.     for (;  source[offset+i]==' ' && i<lim - 1;  i++);
  1034.  
  1035.     /* copy word over */
  1036.     for (j = 0; j < i; j++)  dest[j] = source[offset+j];
  1037.     dest[j] = 0;    /* null to tie off string */
  1038.  
  1039.     return(offset+i);
  1040. }
  1041.  
  1042. /*
  1043.  * putWord()
  1044.  *
  1045.  * This function writes one word to modem & console.
  1046.  */
  1047. void putWord(char *st)
  1048. {
  1049.     char *s;
  1050.     int  newColumn;
  1051.     static char prevChar = 0;
  1052.  
  1053.     for (newColumn = crtColumn, s = st;  *s; s++)   {
  1054.     if (*s != TAB) {
  1055.         if (*s == '\b') newColumn--;
  1056.         else ++newColumn;
  1057.     }
  1058.     else    while (++newColumn % 8);
  1059.     }
  1060.     if (newColumn > termWidth) {
  1061.     fprintf(upfd, "\n");
  1062.     crtColumn = 1;
  1063.     }
  1064.  
  1065.     for (;  *st;  st++) {
  1066.  
  1067.     if (*st != TAB) {
  1068.         if (*st == '\b') crtColumn--;
  1069.         else ++crtColumn;
  1070.     }
  1071.     else    while (++crtColumn % 8);
  1072.  
  1073.     /* worry about words longer than a line:    */
  1074.     if (crtColumn > termWidth) {
  1075.         fprintf(upfd, "\n");
  1076.         crtColumn = 1;
  1077.     }
  1078.  
  1079.     if (*st == '\n' && EOP) {
  1080.         fprintf(upfd, "\n");
  1081.         crtColumn = 1;
  1082.     }
  1083.     else if (prevChar!=NEWLINE  ||  (*st > ' ')) {
  1084.         putc(*st, upfd); prevChar = *st;
  1085.         if (*st > ' ') EOP = FALSE;
  1086.     }
  1087.     else {
  1088.         fprintf(upfd, "\n");
  1089.         crtColumn = 1;
  1090.         if (*st == '\n' && !EOP) {
  1091.         fprintf(upfd, "\n");
  1092.         crtColumn = 1;
  1093.         }
  1094.         else putc(*st, upfd), prevChar = *st;
  1095.         EOP = TRUE;
  1096.     }
  1097.     }
  1098. }
  1099.  
  1100.